all repos — caroster @ 7aaf2e08839a69d11fe38936bef5abaf5789b853

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import Box from '@material-ui/core/Box';
  3import {makeStyles, useTheme} from '@material-ui/core/styles';
  4import {useTranslation} from 'react-i18next';
  5import {initializeApollo} from '../../lib/apolloClient';
  6import useToastStore from '../../stores/useToastStore';
  7import useEventStore from '../../stores/useEventStore';
  8import Layout from '../../layouts/Default';
  9import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
 10import TravelColumns from '../../containers/TravelColumns';
 11import NewTravelDialog from '../../containers/NewTravelDialog';
 12import VehicleChoiceDialog from '../../containers/VehicleChoiceDialog';
 13import WelcomeDialog from '../../containers/WelcomeDialog';
 14import EventBar from '../../containers/EventBar';
 15import Loading from '../../containers/Loading';
 16import OnBoardingTour from '../../containers/OnBoardingTour';
 17import {
 18  useUpdateEventMutation,
 19  Event as EventType,
 20  useEventByUuidQuery,
 21  EventByUuidDocument,
 22  EditEventInput,
 23  useFindUserVehiclesQuery,
 24} from '../../generated/graphql';
 25import ErrorPage from '../_error';
 26import useProfile from '../../hooks/useProfile';
 27import Fab from '../../containers/Fab';
 28import useMediaQuery from '@material-ui/core/useMediaQuery';
 29import useBannerStore from '../../stores/useBannerStore';
 30import DrawerMenu from '../../containers/DrawerMenu';
 31
 32const POLL_INTERVAL = 10000;
 33
 34interface Props {
 35  event: EventType;
 36  eventUUID: string;
 37}
 38
 39const EventPage = props => {
 40  const {t} = useTranslation();
 41  const {event} = props;
 42  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 43  return <Event {...props} />;
 44};
 45
 46const Event = (props: Props) => {
 47  const {eventUUID} = props;
 48  const bannerOffset = useBannerStore(s => s.offset);
 49  const classes = useStyles({bannerOffset});
 50  const theme = useTheme();
 51  const {t} = useTranslation();
 52  const {user} = useProfile();
 53  const {data: {me: {profile: {vehicles = []} = {}} = {}} = {}, loading} =
 54    useFindUserVehiclesQuery();
 55  const addToast = useToastStore(s => s.addToast);
 56  const setEvent = useEventStore(s => s.setEvent);
 57  const eventUpdate = useEventStore(s => s.event);
 58  const setIsEditing = useEventStore(s => s.setIsEditing);
 59  const [updateEvent] = useUpdateEventMutation();
 60  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 61  const [openNewTravelContext, toggleNewTravel] = useState({opened: false});
 62  const [openVehicleChoice, toggleVehicleChoice] = useReducer(i => !i, false);
 63  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 64    pollInterval: POLL_INTERVAL,
 65    variables: {uuid: eventUUID},
 66  });
 67  const matches = useMediaQuery(theme.breakpoints.down('sm'));
 68  const addCarClasses = matches ? 'tour_travel_add' : '';
 69
 70  useEffect(() => {
 71    if (event) setEvent(event as EventType);
 72  }, [event]);
 73
 74  const onSave = async e => {
 75    try {
 76      const {uuid, ...data} = eventUpdate;
 77      const {id, __typename, travels, users, waitingList, ...input} = data;
 78      await updateEvent({
 79        variables: {uuid, eventUpdate: input as EditEventInput},
 80        refetchQueries: ['eventByUUID'],
 81      });
 82      setIsEditing(false);
 83    } catch (error) {
 84      console.error(error);
 85      addToast(t('event.errors.cant_update'));
 86    }
 87  };
 88
 89  const addTravelClickHandler =
 90    user && vehicles?.length != 0
 91      ? toggleVehicleChoice
 92      : () => toggleNewTravel({opened: true});
 93
 94  if (!event || loading) return <Loading />;
 95
 96  return (
 97    <Layout
 98      className={classes.layout}
 99      pageTitle={t('event.title', {title: event.name})}
100      menuTitle={t('event.title', {title: event.name})}
101      displayMenu={false}
102    >
103      <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} />
104      <DrawerMenu />
105      <TravelColumns toggle={addTravelClickHandler} />
106      <Box className={classes.bottomRight}>
107        <Fab
108          onClick={addTravelClickHandler}
109          aria-label="add-car"
110          color="primary"
111          className={addCarClasses}
112        >
113          {t('travel.creation.title')}
114        </Fab>
115      </Box>
116      <NewTravelDialog
117        context={openNewTravelContext}
118        toggle={() => toggleNewTravel({opened: false})}
119      />
120      <VehicleChoiceDialog
121        open={openVehicleChoice}
122        toggle={toggleVehicleChoice}
123        toggleNewTravel={toggleNewTravel}
124        vehicles={vehicles}
125      />
126      <AddToMyEventDialog
127        event={event}
128        open={isAddToMyEvent}
129        onClose={() => setIsAddToMyEvent(false)}
130      />
131      <WelcomeDialog />
132      <OnBoardingTour />
133    </Layout>
134  );
135};
136
137export async function getServerSideProps(ctx) {
138  const {uuid} = ctx.query;
139  const apolloClient = initializeApollo();
140  const {data = {}} = await apolloClient.query({
141    query: EventByUuidDocument,
142    variables: {uuid},
143  });
144  const {eventByUUID: event} = data;
145  const {host = ''} = ctx.req.headers;
146
147  return {
148    props: {
149      event,
150      eventUUID: uuid,
151      metas: {
152        title: event?.name || '',
153        url: `https://${host}${ctx.resolvedUrl}`,
154      },
155    },
156  };
157}
158
159const useStyles = makeStyles(theme => ({
160  layout: ({bannerOffset}) => ({
161    paddingTop: theme.mixins.toolbar.minHeight + bannerOffset,
162  }),
163  bottomRight: {
164    position: 'absolute',
165    bottom: theme.spacing(1),
166    right: theme.spacing(6),
167    width: 200,
168    [theme.breakpoints.down('sm')]: {
169      right: theme.spacing(1),
170    },
171  },
172}));
173
174export default EventPage;